#ifndef _MINIX_H
#define _MINIX_H

#include <cnix/types.h>
#include <cnix/string.h>
#include <cnix/errno.h>
#include <cnix/fs.h>
#include <cnix/mm.h>
#include <cnix/kernel.h>

struct minix_super_block{
	unsigned short	s_ninodes;	// total inodes'number
	unsigned short	s_nzones;	// V1 total zones'number, include bitmap
	short		s_imblocks;	// inode map blocks
	short		s_zmblocks;	// zone map blocks
	unsigned short	s_fdzone;	// first data zone number
	short		s_lzsize;	// log of zone size
	long		s_msize;	// max file size
	short		s_magic;	// magic number
	short		s_pad;		// padding
	unsigned long	s_zones;	// V2 total zones'number, include bitmap

	// below, in memory
	unsigned long	s_isearch;
	unsigned long	s_zsearch;

	int		s_version;
	int		s_ipblock;	// inodes'number per block

	int		s_ndzones;
	int		s_nindirs;
};

// V2, 30 char names
#define LM_MAGIC 0x2478

#define u32size			(sizeof(unsigned long))
#define u32bits			(u32size * 8)	
#define BITS_PER_BLOCK		(BLOCKSIZ * 8)
#define INODES_PER_BLOCK	(BLOCKSIZ / INODE_SIZE)

#define NR_ZONES	10
#define NR_DZONES	7
#define NR_INDIRECTS	(BLOCKSIZ / sizeof(unsigned long))

#define LZSIZE		0
#define ZONE_SIZE	(BLOCKSIZ << LZSIZE)

// assume zone size is the same as block size
#define FILESIZE_MAX	\
	(NR_DZONES * ZONE_SIZE + NR_INDIRECTS * ZONE_SIZE \
	+ NR_INDIRECTS * NR_INDIRECTS * ZONE_SIZE)

#define BOOT_BLOCK	0
#define SUPER_BLOCK	1
#define SUPER_SIZE	((int)(&(((struct minix_super_block *)(0))->s_isearch)))

#define NOBIT	0
#define NOZONE	0
#define NOBLOCK	0

#define IMAP	0
#define ZMAP	1

struct minix_inode{
	unsigned short	i_mode;
	short		i_nlinks;
	short		i_uid;
	short		i_gid;
	long		i_size;
	long		i_atime;
	long		i_mtime;
	long		i_ctime;
	unsigned long	i_zone[NR_ZONES];

	// in memory
	int		i_ndzones;
	int		i_nindirs;
	struct minix_super_block * i_msb;
};

#define INODE_SIZE	((int)(&(((struct minix_inode *)(0))->i_ndzones)))

struct direct{
	unsigned short d_ino;
	char d_name[30];
};

#define DIRECT_SIZE	sizeof(struct direct)

#define minix_getblk(dev, block) getblk(dev, block, 1024)

extern unsigned long minix_bitalloc(struct super_block * sb, int which);
extern void minix_bitfree(struct super_block * sb, unsigned long bit, int which);

#endif
